/*
# P1967 [NOIP 2013 提高组] 货车运输

## 题目背景

NOIP2013 提高组 D1T3

## 题目描述

A 国有 $n$ 座城市，编号从 $1$ 到 $n$，城市之间有 $m$ 条双向道路。每一条道路对车辆都有重量限制，简称限重。

现在有 $q$ 辆货车在运输货物，司机们想知道每辆车在不超过车辆限重的情况下，最多能运多重的货物。

## 输入格式

第一行有两个用一个空格隔开的整数 $n,m$，表示 A 国有 $n$ 座城市和 $m$ 条道路。  

接下来 $m$ 行每行三个整数 $x, y, z$，每两个整数之间用一个空格隔开，表示从 $x$ 号城市到 $y$ 号城市有一条限重为 $z$ 的道路。    
注意：$x \neq y$，两座城市之间可能有多条道路。

接下来一行有一个整数 $q$，表示有 $q$ 辆货车需要运货。

接下来 $q$ 行，每行两个整数 $x,y$，之间用一个空格隔开，表示一辆货车需要从 $x$ 城市运输货物到 $y$ 城市，保证 $x \neq y$。

## 输出格式

共有 $q$ 行，每行一个整数，表示对于每一辆货车，它的最大载重是多少。  
如果货车不能到达目的地，输出 $-1$。

## 输入输出样例 #1

### 输入 #1

```
4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3
```

### 输出 #1

```
3
-1
3
```
*/

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

class App {
	vector<vector<int>> edges;
	vector<int> father;
	int cnt = 1;
	vector<int> head;
	vector<int> next;
	vector<int> to;
	vector<int> weight;

	int power = 0;
	vector<int> vis;
	vector<int> deep;
	vector<vector<int>> stjump, stmin;

	int log2(int n)
	{
		int ans = 0;
		while ((1 << ans) <= (n >> 1)) {
			ans++;
		}

		return ans;
	}

	void addedge(int u, int v, int w)
	{
		next[cnt] = head[u];
		to[cnt] = v;
		weight[cnt] = w;
		head[u] = cnt++;
	}

	int find(int x)
	{
		return x == father[x] ? x : father[x] = find(father[x]);
	}

	void kruskal()
	{
		for (int i = 0, u, v; i < edges.size(); i++) {
			u = edges[i][0];
			v = edges[i][1];
			int fu = find(u);
			int fv = find(v);
			if (fu != fv) {
				father[fu] = fv;
				addedge(u, v, edges[i][2]);
				addedge(v, u, edges[i][2]);
			}
		}
	}

	void dfs(int u, int f, int w)
	{
		vis[u] = 1;
		if (f == 0) {
			deep[u] = 1;
			stjump[u][0] = u;
			stmin[u][0] = INT32_MAX;
		} else {
			deep[u] = deep[f] + 1;
			stjump[u][0] = f;
			stmin[u][0] = w;
		}
		for (int p = 1; p <= power; p++) {
			stjump[u][p] = stjump[stjump[u][p - 1]][p - 1];
			stmin[u][p] = min(stmin[u][p - 1], stmin[stjump[u][p - 1]][p - 1]);
		}

		for (int e = head[u]; e; e = next[e]) {
			if (!vis[to[e]]) {
				dfs(to[e], u, weight[e]);
			}
		}
	}

	void build(int n, int m)
	{
		for (int i = 0; i < m; i++) {
			cin >> edges[i][0] >> edges[i][1] >> edges[i][2];
		}
		sort(edges.begin(), edges.end(), [](auto a, auto b) { return a[2] > b[2]; });
		kruskal();

		for (int i = 1; i <= n; i++) {
			if (!vis[i]) {
				dfs(i, 0, 0);
			}
		}
	}

    public:
	App(int n, int m)
		: edges(m, vector<int>(3, 0)), father(n + 1, 0), head(n + 1, 0), next((m << 1) + 1, 0), to((m << 1) + 1, 0), weight((m << 1) + 1, 0), //
		  power(log2(n)), vis(n + 1, 0), deep(n + 1, 0), stjump(n + 1, vector<int>(power + 1, 0)), stmin(stjump)
	{
		for (int i = 0; i < father.size(); i++) {
			father[i] = i;
		}
		build(n, m);
	}

	int lca(int u, int v)
	{
		if (find(u) != find(v)) {
			return -1;
		}

		if (deep[u] < deep[v]) {
			swap(u, v);
		}

		int k = deep[u] - deep[v];
		int ans = INT32_MAX;
		for (int p = log2(k); p >= 0; p--) {
			if (deep[stjump[u][p]] >= deep[v]) {
				ans = min(ans, stmin[u][p]);
				u = stjump[u][p];
			}
		}
                if(u == v){
                        return ans;
                }

                for(int p = log2(deep[u] - 1); p >= 0; p--){
                        if(stjump[u][p] != stjump[v][p]){
                                ans = min({ans, stmin[u][p], stmin[v][p]});
                                u = stjump[u][p];
                                v = stjump[v][p];
                        }
                }

                return min({ans, stmin[u][0], stmin[v][0]});
	}

	void run()
	{
		int q = 0;
                cin >> q;
		for (int i = 0, u, v; i < q; i++) {
			cin >> u >> v;
                        cout << lca(u, v) << '\n';
		}
	}
};

int main()
{
	int n, m;
	cin >> n >> m;
	App app(n, m);
        app.run();

	return 0;
}